home *** CD-ROM | disk | FTP | other *** search
- /* ------------------------ DPMIDVT.C --------------------------- */
- /* DPMI interface code to DemoVT v1.5 and higher. */
- /* Written bye Jare of Iguana in 1994. */
- /* -------------------------------------------------------------- */
- /* Thanks to Yann for supplying all those specs, and also to Tran */
- /* of nothing for getting me into this wonderful world of PMode. */
- /* -------------------------------------------------------------- */
- /* This code will compile under Watcom C++ 9.5. I think it should */
- /* work also with other versions and under other 32 bit compilers */
- /* but I haven't bothered to test. */
- /* -------------------------------------------------------------- */
- /* You will find some general purpose DPMI code here. Use it! */
- /* Especially that RealModeMem variable. */
- /* That variable is not necessary under DOS4GW, because the first */
- /* megabyte is directly accesible using the default data seg. But */
- /* I have included it to make this code fully portable to other, */
- /* more hostile environments. */
- /* You might need to translate it to assembly, but that should be */
- /* easy. After all, it's your job! :) */
- /* -------------------------------------------------------------- */
-
- #include <stdlib.h>
-
- #include "pump.h"
-
- typedef struct SDPMI_rminfo { // Real mode registers for the DPMI
- dword EDI; // translation API.
- dword ESI;
- dword EBP;
- dword _reserved;
- dword EBX;
- dword EDX;
- dword ECX;
- dword EAX;
- word flags;
- word ES, DS, FS, GS;
- word IP, CS, SP, SS;
- } TDPMI_RealModeInfo;
-
- #define FLAGS_CARRY 0x0001 // To check flags above.
- #define FLAGS_PARITY 0x0004
- #define FLAGS_AUX 0x0010
- #define FLAGS_ZERO 0x0040
- #define FLAGS_SIGN 0x0080
-
-
-
- static TDPMI_RealModeInfo DPMI_rmi;
-
- static union REGS rmregs;
- static struct SREGS rmsregs;
-
- static void DPMI_RealModeCall(void) {
- DPMI_rmi.SS = DPMI_rmi.SP = 0; // DPMI host will provide its own stack.
- rmregs.h.bh = 0; // Do not reset PIC or A20 gate.
- rmregs.w.cx = 0; // 0 words of parameters on the stack.
- rmregs.x.edi = FP_OFF(&DPMI_rmi); // Real mode info.
- rmsregs.es = FP_SEG(&DPMI_rmi);
- int386x(0x31, &rmregs, &rmregs, &rmsregs);
- }
-
- static void DPMI_RealModeInt(int i) {
- rmregs.w.ax = 0x300;
- rmregs.h.bl = i;
- DPMI_RealModeCall();
- }
-
- static void DPMI_RealModeProc(word seg, word off) {
- /*
- rmregs.w.ax = 0x301;
- DPMI_rmi.CS = seg;
- DPMI_rmi.IP = off;
- DPMI_RealModeCall();
-
- ********************************************************
- WARNING: DOS4GW v1.8 bundled with WATCOM C++ 9.5 doesn't
- seem to suuport the above call (at least I didn't get it
- to work), so we used a wierd scheme to emulate it.
- JCAB - 2/94
- DOS4GW 1.95 doesn't work either. What's going on?
- Jare - 3/94
- ********************************************************
- */
-
- dword _far *vectable = (dword _far *)RealModeMem;
- dword oldvec4 = vectable[4];
- dword oldvec6 = vectable[6];
- dword oldvec7 = vectable[7];
-
- // None of these interrupts should occur during normal operation.
- // but the way to do would be to allocate Real Mode Memory and place
- // the call there. INT 4 still should be used. I hate this!
- vectable[4] = 6*4+1; // Address of INT6 vector.
- vectable[6] = (long)0x9A00 + ((long)off<<16); // FAR CALL [seg:off]
- vectable[7] = (long)seg + ((long)0xCF<<16); // + IRET
- DPMI_RealModeInt(4);
-
- vectable[4] = oldvec4;
- vectable[6] = oldvec6;
- vectable[7] = oldvec7;
-
- }
-
- static void _far * DPMI_MapRealModeSegment(word rmseg) {
-
- rmregs.x.eax = 0x0002;
- rmregs.x.ebx = (dword)rmseg;
- int386(0x31, &rmregs, &rmregs);
-
- // if (rmregs.x.cflag & FLAGS_CARRY)
- // return NULL;
- // else
- return MK_FP(rmregs.w.ax, 0);
- }
-
- static byte _far *DPMI_MapMemory(dword baseaddr, dword len) {
- word selector;
-
- rmregs.x.eax = 0x0000; // Allocate descriptor.
- rmregs.x.ecx = 1; // One descriptor.
- int386(0x31, &rmregs, &rmregs);
- // if (rmregs.x.cflag & FLAGS_CARRY)
- // return NULL;
- selector = rmregs.w.ax;
-
- rmregs.x.eax = 0x0007; // Set selector base address.
- rmregs.x.ebx = (dword)selector;
- rmregs.x.edx = (dword)((word)baseaddr);
- rmregs.x.ecx = (dword)(baseaddr >> 16);
- int386(0x31, &rmregs, &rmregs);
- // if (!(rmregs.x.cflag & FLAGS_CARRY))
- {
- rmregs.x.eax = 0x0009; // Set descriptor access rights.
- rmregs.x.ebx = (dword)selector;
- rmregs.x.ecx = 0xCF93;
- int386(0x31, &rmregs, &rmregs);
- // if (!(rmregs.x.cflag & FLAGS_CARRY))
- {
- rmregs.x.eax = 0x0008; // Set segment limit.
- rmregs.x.ebx = (dword)selector;
- rmregs.x.edx = (dword)((word)len);
- rmregs.x.ecx = (dword)(len >> 16);
- int386(0x31, &rmregs, &rmregs);
- if (!(rmregs.x.cflag & FLAGS_CARRY))
- return (MK_FP(selector, 0)); // Everything OK.
- // puts("Error setting limit");
- }
- // else
- ;//puts("Error setting rights.");
- }
- // else
- ;//puts("Error setting base address.");
-
- // Something went wrong, so we free the selector.
- rmregs.x.eax = 0x0001; // Free selector.
- rmregs.x.ebx = (dword)selector;
- int386(0x31, &rmregs, &rmregs);
- // We don't care about errors freeing the selector. Can't do
- // much about it I guess.
- return NULL;
- }
-
- // -------------------------------------------------------
-
- // -------------------------------------------------------
-
- byte _far *RealModeMem = NULL;
- dword DVTAppIdFound = 0;
- volatile TDVTInfo _far *DVTInfo = NULL;
-
-
- int DVT_Init(void) {
- int present;
- byte _far *p;
-
- if (DVTInfo != NULL) // Already initialized?
- return 1;
- DPMI_rmi.EAX = 0x5654; // DemoVT magic numbers.
- DPMI_rmi.EBX = 0x5472;
- DPMI_rmi.ECX = 0x6163;
- DPMI_rmi.EDI = 0;
- DPMI_rmi.ES = 0;
- DPMI_RealModeInt(0x2F); // Perform call.
-
- present = ( (word)DPMI_rmi.EAX == 0 // Complex check.
- && (word)DPMI_rmi.EBX == 0x3F17
- && (word)DPMI_rmi.ECX == 0x1343);
- if (present) { // Allocate far pointer.
- p = DPMI_MapMemory(0, 1024*1024-1);
- if (p != NULL) {
- word _far *g;
- RealModeMem = p;
- DVTAppIdFound = (dword)((DPMI_rmi.ES << 4)
- + (word)(DPMI_rmi.EDI));
- g = (word _far *) (p + DVTAppIdFound - 4);
- DVTInfo = (TDVTInfo _far *)(p + g[0] + (g[1] << 4));
- }
- }
- return present;
- }
-
- void DVT_CallDemoVT(int command) {
- if (DVTInfo == NULL // Not initialized?
- || command < 0 || command > 3) // or invalid parameter?
- return;
- DPMI_rmi.EAX = command;
- DPMI_RealModeProc(DVTInfo->entryPointAXSeg, DVTInfo->entryPointAXOff);
- }
-
- dword DVT_GetTickCounter(void) {
- if (DVTInfo == NULL) // Not initialized?
- return 0;
- return DVTInfo->tickCounter;
- }
-
- void DVT_WaitForStart(void) {
- if (DVTInfo == NULL) // Not initialized?
- return;
- DVTInfo->tickCounter = 0;
- while (DVTInfo->tickCounter < 25)
- DVT_CallMusic();
- DVTInfo->tickCounter = 0;
- }
-
- void DVT_JumpPos(byte pattern, byte note) {
- if (DVTInfo == NULL) // Not initialized?
- return;
- DVTInfo->jumpPosSeq = pattern;
- DVTInfo->jumpPosNote = note;
- DVTInfo->jumpNewPos = 1;
- }
-
- byte DVT_GetSemaphore(byte nsem) {
- if (DVTInfo == NULL) // Not initialized?
- return 0;
- return DVTInfo->semaphores[nsem];
- }
-
- void DVT_SetSemaphore(byte nsem, byte value) {
- if (DVTInfo == NULL) // Not initialized?
- return;
- DVTInfo->semaphores[nsem] = value;
- }
-
- void DVT_MiddleSync(byte nsem, byte pattern, byte note) {
- if (DVTInfo == NULL || nsem > 255) // Not initialized or error?
- return;
-
- if (nsem == 255 || DVT_GetSemaphore(nsem) == 0)
- DVT_JumpPos(pattern, note);
- while (nsem < 255 && DVT_GetSemaphore(nsem+1) == 0);
- }
-
- byte DVT_GetSoundVolume(void) {
- if (DVTInfo == NULL) // Not initialized?
- return 255;
- return DVTInfo->soundVolume;
- }
-
- void DVT_SetSoundVolume(byte vol) {
- if (DVTInfo == NULL) // Not initialized?
- return;
- DVTInfo->soundVolume = vol;
- }
-
- /* ------------------------ DPMIDVT.C --------------------------- */
-
-